#pragma once
#include "Utils.h"
#include <msclr/lock.h>



namespace NumberPlateReader {

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;
	using namespace MODI;
	using namespace System::Threading;
	using namespace msclr;
	using namespace System::Drawing::Imaging;
	using namespace System::Collections::Generic;
	using namespace System::IO;


	/// <summary>
	/// Summary for Form1
	///
	/// WARNING: If you change the name of this class, you will need to change the
	///          'Resource File Name' property for the managed resource compiler tool
	///          associated with all .resx files this class depends on.  Otherwise,
	///          the designers will not be able to interact properly with localized
	///          resources associated with this form.
	/// </summary>
	public ref class frmNumberPlateReader : public System::Windows::Forms::Form
	{
	public:
		int camNum;
		static CvHaarClassifierCascade* cascade = 0;
		CvCapture* m_capture;
		static CvMemStorage* storage = 0;
		IplImage* img;
	private: System::Windows::Forms::Button^  btnStartCapture;
	private: System::Windows::Forms::Timer^  tmrGetVideo;
	private: System::Windows::Forms::ListBox^  lstTextFound;

	private: System::Windows::Forms::Timer^  tmrProcessImages;




	public: 

	public: 
		IplImage* frame_copy;

		frmNumberPlateReader(void)
		{
			InitializeComponent();
			incrDelegate = gcnew incrementDelegate(this, &frmNumberPlateReader::IncrementProgressBar);
			listResultDelegateImpl = gcnew listResultDelegate(this, &frmNumberPlateReader::ListResults);
			tmrProcessImages->Enabled = true;
		}

	protected:
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		~frmNumberPlateReader()
		{
			if (components)
			{
				delete components;
			}
		}
	private: System::Windows::Forms::PictureBox^  pictureBoxCapturedImage;
	protected: 

	private: System::ComponentModel::IContainer^  components;
	protected: 

	private:
		/// <summary>
		/// Required designer variable.
		/// </summary>


#pragma region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		void InitializeComponent(void)
		{
			this->components = (gcnew System::ComponentModel::Container());
			this->pictureBoxCapturedImage = (gcnew System::Windows::Forms::PictureBox());
			this->btnStartCapture = (gcnew System::Windows::Forms::Button());
			this->tmrGetVideo = (gcnew System::Windows::Forms::Timer(this->components));
			this->lstTextFound = (gcnew System::Windows::Forms::ListBox());
			this->tmrProcessImages = (gcnew System::Windows::Forms::Timer(this->components));
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->pictureBoxCapturedImage))->BeginInit();
			this->SuspendLayout();
			// 
			// pictureBoxCapturedImage
			// 
			this->pictureBoxCapturedImage->Location = System::Drawing::Point(12, 12);
			this->pictureBoxCapturedImage->Name = L"pictureBoxCapturedImage";
			this->pictureBoxCapturedImage->Size = System::Drawing::Size(427, 279);
			this->pictureBoxCapturedImage->TabIndex = 0;
			this->pictureBoxCapturedImage->TabStop = false;
			// 
			// btnStartCapture
			// 
			this->btnStartCapture->Location = System::Drawing::Point(12, 297);
			this->btnStartCapture->Name = L"btnStartCapture";
			this->btnStartCapture->Size = System::Drawing::Size(144, 23);
			this->btnStartCapture->TabIndex = 1;
			this->btnStartCapture->Text = L"Start Capture";
			this->btnStartCapture->UseVisualStyleBackColor = true;
			this->btnStartCapture->Click += gcnew System::EventHandler(this, &frmNumberPlateReader::btnStartCapture_Click);
			// 
			// tmrGetVideo
			// 
			this->tmrGetVideo->Enabled = true;
			this->tmrGetVideo->Interval = 1000;
			this->tmrGetVideo->Tick += gcnew System::EventHandler(this, &frmNumberPlateReader::tmrGetVideo_Tick);
			// 
			// lstTextFound
			// 
			this->lstTextFound->FormattingEnabled = true;
			this->lstTextFound->Location = System::Drawing::Point(162, 297);
			this->lstTextFound->Name = L"lstTextFound";
			this->lstTextFound->Size = System::Drawing::Size(276, 121);
			this->lstTextFound->TabIndex = 2;
			// 
			// tmrProcessImages
			// 
			this->tmrProcessImages->Interval = 1000;
			this->tmrProcessImages->Tick += gcnew System::EventHandler(this, &frmNumberPlateReader::tmrProcessImages_Tick);
			// 
			// frmNumberPlateReader
			// 
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(452, 489);
			this->Controls->Add(this->lstTextFound);
			this->Controls->Add(this->btnStartCapture);
			this->Controls->Add(this->pictureBoxCapturedImage);
			this->Name = L"frmNumberPlateReader";
			this->Text = L"Number Plate Reader";
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^  >(this->pictureBoxCapturedImage))->EndInit();
			this->ResumeLayout(false);

		}
#pragma endregion
	private: System::Void btnStartCapture_Click(System::Object^  sender, System::EventArgs^  e) 
			 {
				 storage = cvCreateMemStorage(0);
				 m_capture = cvCaptureFromCAM(0);
				 tmrGetVideo->Start();
			 }

	private: System::Void tmrGetVideo_Tick(System::Object^  sender, System::EventArgs^  e) 
			 {
				 IplImage* img = cvQueryFrame(m_capture);
				 if( !img)
					 return;

				 if( img->width <= 0 || img->height <= 0 )
					 return;

				 img = Utils::drawSquares( img, Utils::findSquares4( img, storage ) );

				 pictureBoxCapturedImage->Image = Utils::IplImageToBitmap(img);
				 pictureBoxCapturedImage->Refresh();
			 }

			 static tessnet2::Tesseract ^ocr = gcnew tessnet2::Tesseract();
			 static bool ocrInit = false;
			 static bool canProcessOcr = true;

			 Void TesseractOCR(String ^fileToOCR)
			 {
				 if( ocrInit == false )
				 {
					 ocr->Init("ENG", false);
					 ocr->OcrDone = gcnew tessnet2::Tesseract::OcrDoneHandler( this, &frmNumberPlateReader::HandleOCRDone );
					 ocr->ProgressEvent += gcnew tessnet2::Tesseract::ProgressHandler( this , &frmNumberPlateReader::HandleOCRProgress  );
					 ocrInit = true;
				 }

				 if( !File::Exists(Application::StartupPath + "\\ProcessedImages\\" + fileToOCR->Substring(fileToOCR->LastIndexOf("\\"))))
				 {
					 File::Move(fileToOCR, Application::StartupPath + "\\ProcessedImages\\" + fileToOCR->Substring(fileToOCR->LastIndexOf("\\")));
				 }
				 else
				 {
					 File::Delete(fileToOCR);
				 }

				 Bitmap ^bmp = gcnew Bitmap(Application::StartupPath + "\\ProcessedImages\\" + fileToOCR->Substring(fileToOCR->LastIndexOf("\\")));
				 ocr->DoOCR(bmp, Rectangle::Empty);
			 }

	public: delegate void incrementDelegate(int x);
			incrementDelegate ^incrDelegate;

			delegate void listResultDelegate(List<tessnet2::Word ^> ^words);
			listResultDelegate ^listResultDelegateImpl;

			Void HandleOCRProgress(int x)
			{
				//BeginInvoke(incrDelegate, x);
			}

			Void HandleOCRDone(List<tessnet2::Word ^> ^words)
			{
				BeginInvoke(listResultDelegateImpl, words);
			}

			Void IncrementProgressBar(int x)
			{
				//prgsBarOCRProgress->Increment(x);
			}

			Void ListResults(List<tessnet2::Word ^> ^words)
			{
				for( int x = 0; x < words->Count; x++ )
					lstTextFound->Items->Add(words[x]);

				canProcessOcr = true;
			}

	private: System::Void tmrProcessImages_Tick(System::Object^  sender, System::EventArgs^  e) 
			 {
				 array<String^, 1> ^readyFiles = Directory::GetFiles(Application::StartupPath + "\\RectangleImages");

				 Console::WriteLine(readyFiles->Length.ToString() + " Files ready for OCR");
				 for(int x = 0; x < readyFiles->Length; x++ )
				 {
					 if( canProcessOcr )
					 {
						 canProcessOcr = false;
						 TesseractOCR(readyFiles[x]->ToString());
					 }
				 }
			 }
	};
}